package id.co.rho.scoring.cid.client.scaffold.ioc;

import id.co.rho.scoring.cid.client.command.CommandDispatcher;
import id.co.rho.scoring.cid.client.command.CommandDispatcherAsync;
import id.co.rho.scoring.cid.client.managed.request.ApplicationRequestFactory;
import id.co.rho.scoring.cid.client.mvc.AppView;
import id.co.rho.scoring.cid.client.mvc.NavigationView;
import id.co.rho.scoring.cid.client.mvc.compare.CompareModelUI;
import id.co.rho.scoring.cid.client.mvc.compare.CompareModelUIWeb;
import id.co.rho.scoring.cid.client.mvc.compare.CompareModelView;
import id.co.rho.scoring.cid.client.mvc.login.LoginUI;
import id.co.rho.scoring.cid.client.mvc.login.LoginUIWeb;
import id.co.rho.scoring.cid.client.mvc.login.LoginView;
import id.co.rho.scoring.cid.client.mvc.model.ModelSearchUI;
import id.co.rho.scoring.cid.client.mvc.model.ModelSearchUIWeb;
import id.co.rho.scoring.cid.client.mvc.model.ModelSearchView;
import id.co.rho.scoring.cid.client.mvc.score.UploadAnswerUI;
import id.co.rho.scoring.cid.client.mvc.score.UploadAnswerUIWeb;
import id.co.rho.scoring.cid.client.mvc.score.UploadAnswerView;
import id.co.rho.scoring.cid.client.mvc.scoringmodel.ScoringModelEditUI;
import id.co.rho.scoring.cid.client.mvc.scoringmodel.ScoringModelEditUIWeb;
import id.co.rho.scoring.cid.client.mvc.scoringmodel.ScoringModelEditView;
import id.co.rho.scoring.cid.client.mvc.scoringmodel.ScoringModelUI;
import id.co.rho.scoring.cid.client.mvc.scoringmodel.ScoringModelUIWeb;
import id.co.rho.scoring.cid.client.mvc.scoringmodel.ScoringModelView;
import id.co.rho.scoring.cid.client.mvc.typemodelconfig.TypeModelConfigUI;
import id.co.rho.scoring.cid.client.mvc.typemodelconfig.TypeModelConfigUIWeb;
import id.co.rho.scoring.cid.client.mvc.typemodelconfig.TypeModelConfigView;
import id.co.rho.scoring.cid.client.mvc.typemodelconfigsearch.TypeModelConfigSearchUI;
import id.co.rho.scoring.cid.client.mvc.typemodelconfigsearch.TypeModelConfigSearchUIWeb;
import id.co.rho.scoring.cid.client.mvc.typemodelconfigsearch.TypeModelConfigSearchView;
import id.co.rho.scoring.cid.client.mvc.upload.UploadModelUI;
import id.co.rho.scoring.cid.client.mvc.upload.UploadModelUIWeb;
import id.co.rho.scoring.cid.client.mvc.upload.UploadModelView;
import id.co.rho.scoring.cid.client.mvc.versioning.VersioningModelUI;
import id.co.rho.scoring.cid.client.mvc.versioning.VersioningModelUIWeb;
import id.co.rho.scoring.cid.client.mvc.versioning.VersioningModelView;
import id.co.rho.scoring.cid.client.mvc.versioning.VersioningSetDefaultUI;
import id.co.rho.scoring.cid.client.mvc.versioning.VersioningSetDefaultUIWeb;
import id.co.rho.scoring.cid.client.mvc.versioning.VersioningSetDefaultView;
import id.co.rho.scoring.cid.client.scaffold.request.EventSourceRequestTransport;
import id.co.rho.scoring.cid.client.security.Credential;
import id.co.rho.scoring.cid.client.security.CredentialConfigurer;
import id.co.rho.scoring.cid.client.security.impl.RealCredential;
import id.co.rho.scoring.cid.client.utils.LoginCheck;
import id.co.rho.scoring.cid.client.utils.LoginCheckImpl;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.inject.client.AbstractGinModule;
import com.google.gwt.place.shared.PlaceController;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

public class ScaffoldModule extends AbstractGinModule {

    @Override
    protected void configure() {
        bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class);
        bind(ApplicationRequestFactory.class).toProvider(RequestFactoryProvider.class).in(Singleton.class);
        bind(PlaceController.class).toProvider(PlaceControllerProvider.class).in(Singleton.class);
        bind(CommandDispatcherAsync.class).toProvider(CommandDispatcherFactoryProvider.class).in(Singleton.class);
        

        bind(Credential.class).toProvider(RealCredentialFactoryProvider.class).in(Singleton.class);
        bind(CredentialConfigurer.class).toProvider(RealCredentialFactoryProvider.class).in(Singleton.class);

        // views
        bind(NavigationView.class).in(Singleton.class);
        bind(LoginUI.class).to(LoginUIWeb.class).in(Singleton.class);
        
        //todo ganti ke LoginCheckImpl sewaktu production
        bind(LoginCheck.class).to(LoginCheckImpl.class).in(Singleton.class);
        bind(LoginView.class).in(Singleton.class);
       
        //upload model
        bind(UploadModelUI.class).to(UploadModelUIWeb.class).in(Singleton.class);
        bind(UploadModelView.class).in(Singleton.class);
        
        bind(AppView.class).in(Singleton.class);
		
		bind(TypeModelConfigUI.class).to(TypeModelConfigUIWeb.class).in(Singleton.class);
        bind(TypeModelConfigView.class).in(Singleton.class);

        bind(TypeModelConfigSearchUI.class).to(TypeModelConfigSearchUIWeb.class).in(Singleton.class);
        bind(TypeModelConfigSearchView.class).in(Singleton.class);

        bind(ScoringModelUI.class).to(ScoringModelUIWeb.class).in(Singleton.class);
        bind(ScoringModelView.class).in(Singleton.class);
        
        bind(ModelSearchUI.class).to(ModelSearchUIWeb.class).in(Singleton.class);
        bind(ModelSearchView.class).in(Singleton.class);
        
        bind(ScoringModelEditUI.class).to(ScoringModelEditUIWeb.class).in(Singleton.class);
        bind(ScoringModelEditView.class).in(Singleton.class);
        
        bind(UploadAnswerUI.class).to(UploadAnswerUIWeb.class).in(Singleton.class);
        bind(UploadAnswerView.class).in(Singleton.class);
        
        bind(CompareModelUI.class).to(CompareModelUIWeb.class).in(Singleton.class);
        bind(CompareModelView.class).in(Singleton.class);
        
        bind(VersioningModelUI.class).to(VersioningModelUIWeb.class).in(Singleton.class);
        bind(VersioningModelView.class).in(Singleton.class);
        
        bind(VersioningSetDefaultUI.class).to(VersioningSetDefaultUIWeb.class).in(Singleton.class);
        bind(VersioningSetDefaultView.class).in(Singleton.class);
    }

    static class PlaceControllerProvider implements Provider<PlaceController> {
        private final PlaceController placeController;

        @Inject
        public PlaceControllerProvider(EventBus eventBus) {
            this.placeController = new PlaceController(eventBus);
        }

        public PlaceController get() {
            return placeController;
        }
    }

    static class RequestFactoryProvider implements Provider<ApplicationRequestFactory> {
        private final ApplicationRequestFactory requestFactory;

        @Inject
        public RequestFactoryProvider(EventBus eventBus) {
            requestFactory = GWT.create(ApplicationRequestFactory.class);
            requestFactory.initialize(eventBus, new EventSourceRequestTransport(eventBus));
        }

        public ApplicationRequestFactory get() {
            return requestFactory;
        }
    }

    static class CommandDispatcherFactoryProvider implements Provider<CommandDispatcherAsync> {
        private CommandDispatcherAsync dispatcher = GWT.create(CommandDispatcher.class);

        @Override
        public CommandDispatcherAsync get() {
            return dispatcher;
        }
    }
    
    static class RealCredentialFactoryProvider implements Provider<RealCredential> {
        private static RealCredential credential = new RealCredential();

        @Override
        public RealCredential get() {
            return credential;
        }
    }

}
